import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
// import 'package:open_file/open_file.dart';

import '../../../../common/api/index.dart';
import '../../../../common/models/index.dart';
import '../../../../common/utils/index.dart';
import '../../../../common/values/index.dart';
import '../../../../common/widgets/index.dart';
import '../../../common/preview_image/index.dart';
import '../../../common/video_player/index.dart';
import 'index.dart';

class CmsDocumentController extends GetxController implements JsNavigationInterface {
  CmsDocumentController();

  final state = CmsDocumentState();
  final channel = O2FlutterMethodChannelUtils();

  // webview控件的控制器
  final GlobalKey webViewKey = GlobalKey();
  InAppWebViewController? webviewController;
  // webview 通用方法
  final webviewHelper = WebviewHelper();
  // 安装转化js
  var isInstallJsName = false;
  // 拍照 图片选择
  final ImagePicker _imagePicker = ImagePicker();

  final _eventBus = EventBus();

  String? docId;

  /// 在 widget 内存中分配后立即调用。
  @override
  void onInit() {
    super.onInit();
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() {
    var map = Get.arguments;
    if (map != null) {
      state.title = map["title"] ?? "cms_document_title".tr;
      OLogger.d("文档标题 title: ${state.title} ");
      String id = map["documentId"] ?? "";
      OLogger.d("文档id: $id ");
      if (id.isNotEmpty) {
        docId = id;
        _initCmsUrl(id, map["options"]);
      }
    }
    super.onReady();
  }

  @override
  void closeWindow() {
    OLogger.d('执行了 jsapi closeWindow ');
    _eventBus.emit(EventBus.cmsDocumentCloseMsg, 'close');
    Get.back();
  }
  
  @override
  void goBack() {
    OLogger.d('执行了 jsapi goBack ');
    tapBackBtn();
  }
  
  @override
  void setNavigationTitle(String title) {
    OLogger.d('执行了 jsapi setNavigationTitle $title ');
    state.title = title;
  }


  void _initCmsUrl(String id, Map<String, dynamic>? options) async {
    var url = O2ApiManager.instance.getCmsDocumentUrl(id) ?? '';
    if (options != null) {
      var readonly = options['readonly'];
      if (readonly != null && (readonly == 'false' || readonly == false)) {
        url = O2ApiManager.instance.getCmsDocumentEditUrl(id) ?? '';
      }
      for (var element in options.entries) {
        OLogger.i('参数 ${element.key} : ${element.value}');
        url += '&${element.key}=${Uri.encodeComponent('${element.value}')}';
      }
    }
    if (url.isNotEmpty) {
      final uurl = Uri.parse(url);
      var host = O2ApiManager.instance.getWebHost();
      var domain = uurl.host;
      var tokenName = O2ApiManager.instance.tokenName;
      var token = O2ApiManager.instance.o2User?.token ?? '';
      OLogger.d(
          "加载webview cookie，url: $url domain: $domain tokenName: $tokenName token: $token");
      CookieManager cookieManager = CookieManager.instance();
      await cookieManager.setCookie(
          url: uurl,
          name: tokenName,
          value: token,
          domain: (domain.isEmpty ? host : domain));
      state.url = url;
    }
    OLogger.d("打开网址： $url");
  }

  ///
  /// 点击appbar 返回按钮
  ///
  void tapBackBtn() async {
    OLogger.d('执行了 tapBackBtn ');
    if (await webviewController?.canGoBack() == true) {
      webviewController?.goBack();
    } else {
      closeWindow();
    }
  }

  ///
  /// 加载js通道
  ///
  void setupWebviewJsHandler(InAppWebViewController c) async {
    webviewController = c;
    webviewController?.addJavaScriptHandler(
        handlerName: O2.webviewChannelNameCommonKey,
        callback: (msgs) {
          OLogger.d(
              "js 通信， name: ${O2.webviewChannelNameCommonKey} msg: $msgs");
          if (msgs.isNotEmpty) {
            String msg = msgs[0] as String? ?? "";
            _jsChannelMessageReceived(msg);
          }
        });
    webviewHelper.setupWebviewJsHandler(c);
    webviewHelper.setupJsNavigationInterface(this);
  }
  /// webview 加载进度
  void progressChanged(InAppWebViewController c, int p) {
    OLogger.d("o2Webview process progress: $p");
    // 这里把  inappwebview的 js handler 方式修改成 我们自定义的
    if (p == 100 && !isInstallJsName) {
      isInstallJsName = true;
      // o2android
      var js = '''
            if (window.flutter_inappwebview && window.flutter_inappwebview.callHandler) {
              window.o2android = {};
              window.o2android.postMessage = function(message){
                window.flutter_inappwebview.callHandler('o2android', message);
              };
            }
          ''';
      c.evaluateJavascript(source: js);
      OLogger.i("执行o2android转化js完成。。。");
      webviewHelper.changeJsHandlerFunName(c);
    }
  }
 

  ///
  /// 打开附件
  ///
  void _openAttachmentFile(String filePath, String fileName) {
    if (filePath.isImageFileName) {
      PreviewImagePage.open(filePath, fileName);
    } else if (filePath.isVideoFileName) {
      VideoPlayerPage.openLocalVideo(filePath, title: fileName);
    }  else {
      channel.openLocalFile(filePath);
    }
  }

  ///
  /// 接收js通道返回数据
  ///   h5上调用js执行flutter这边的原生方法
  ///
  // void jsChannelMessageReceived(JavascriptMessage message) {
  // if (message.message.isNotEmpty) {
  void _jsChannelMessageReceived(String message) {
    OLogger.d("h5执行原生方法，message: $message");
    if (message.isEmpty) {
      return;
    }
    var jsMessage = JsMessage.fromJson(O2Utils.parseStringToJson(message));
    switch (jsMessage.type) {
      case "closeDocumentWindow":
        OLogger.d("关闭表单");
        closeWindow();
        break;
      case "downloadAttachment":
        _downloadAttachment(jsMessage.data);
        break;
      case "uploadAttachment":
        _uploadAttachment(jsMessage.data);
        break;
      case "uploadAttachmentForDatagrid":
        _uploadAttachment(jsMessage.data, forGrid: true);
        break;
      case "replaceAttachment":
        _replaceAttachment(jsMessage.data);
        break;
      case "replaceAttachmentForDatagrid":
        _replaceAttachment(jsMessage.data, forGrid: true);
        break;
      case "uploadImage2FileStorage": // imageclipper 图片上传控件
        _uploadImage2FileStorage(jsMessage.data);
        break;
      default:
        break;
    }
    _executeCallbackJs(jsMessage.callback, null);
  }

  /// 选择图片 或者 拍照
  /// 图片控件使用
  Future<void> _pickImageByType(int type, Map<String, dynamic> data) async {
    XFile? file;
    if (type == 0) {
      // 相册
      file = await _imagePicker.pickImage(source: ImageSource.gallery);
    } else if (type == 1) {
      // 拍照
      file = await _imagePicker.pickImage(source: ImageSource.camera);
    }
    if (file != null) {
      // var mwfId: String = "",//控件id
      // var callback: String = "",//回调函数
      // var referencetype: String = "",//上传文件服务器的业务类型名称
      // var reference: String = "",//关联业务id
      // var fileId: String = ""//上传返回的文件id
      String referencetype = data['referencetype'] ?? '';
      String reference = data['reference'] ?? '';
      String callback = data['callback'] ?? '';
      if (referencetype.isEmpty || reference.isEmpty || callback.isEmpty) {
        Loading.showError('args_error'.tr);
        return;
      }
      Loading.show();
      var id = await FileAssembleService.to.uploadImageWithReferencetype(
          referencetype, reference, File(file.path));
      if (id != null && id.id != null) {
        data['fileId'] = id.id;
        final back = json.encode(data);
        final js = '$callback(\'$back\')';
        OLogger.d('执行js ：$js');
        await webviewController?.evaluateJavascript(source: js);
        Loading.dismiss();
      }
    }
  }

  ///
  /// 图片上传控件
  ///
  void _uploadImage2FileStorage(Map<String, dynamic>? data) {
    final myContext = Get.context;
    if (data != null && myContext != null) {
      O2UI.showBottomSheetWithCancel(myContext, [
        ListTile(
          onTap: () {
            Navigator.pop(myContext);
            _pickImageByType(0, data);
          },
          title: Align(
            alignment: Alignment.center,
            child: Text('album'.tr,
                style: Theme.of(myContext).textTheme.bodyMedium),
          ),
        ),
        const Divider(height: 1),
        ListTile(
          onTap: () {
            Navigator.pop(myContext);
            _pickImageByType(1, data);
          },
          title: Align(
            alignment: Alignment.center,
            child: Text('take_photo'.tr,
                style: Theme.of(myContext).textTheme.bodyMedium),
          ),
        ),
      ]);
    }
  }

  ///
  /// 下载附件
  ///
  void _downloadAttachment(Map<String, dynamic>? data) async {
    OLogger.d("下载附件");
    if (data != null) {
      String attachmentId = data["attachmentId"] ?? "";
      if (attachmentId.isNotEmpty && docId != null) {
        Loading.show();
        // 请求附件对象信息
        DocAttachmentInfo? info = await CmsAssembleControlService.to
            .getAttachmentInfoByDocId(docId!, attachmentId);
        if (info != null && info.name != null && info.id != null) {
          String? filePath = await O2FilePathUtil.getCmsFileDownloadLocalPath(
              info.id!, info.name!);
          if (filePath == null || filePath.isEmpty) {
            Loading.showError('process_work_download_file_no_path'.tr);
            return;
          }
          var file = File(filePath);
          if (file.existsSync()) {
            Loading.dismiss();
            _openAttachmentFile(filePath, info.name!);
          } else {
            // 下载附件
            var donwloadUrl = CmsAssembleControlService.to
                .downloadAttachmentUrl(attachmentId);
            try {
              await O2HttpClient.instance.downloadFile(donwloadUrl, filePath);
              Loading.dismiss();
              _openAttachmentFile(filePath, info.name!);
            } on Exception catch (e) {
              Loading.showError(e.toString());
            }
          }
        } else {
          Loading.showError('process_work_download_get_attachmentinfo_fail'.tr);
        }
      }
    }
  }

  ///
  /// 上传附件
  ///
  void _uploadAttachment(Map<String, dynamic>? data,
      {bool forGrid = false}) async {
    if (data != null && docId != null) {
      String site = data["site"] ?? "";
      String param = data["param"] ?? "";
      OLogger.d('上传附件 site $site  , param $param');
      O2Utils.pickerFileOrImage((paths) {
        _uploadAttachmentBegin(paths, site, param, forGrid);
      }, allowMultiple: true);
    }
  }

  Future<void> _uploadAttachmentBegin(List<String?> paths, String site, String param, bool forGrid) async {
    Loading.show();
    int errorNumber = 0;
    for (var element in paths) {
      if (element != null && element.isNotEmpty) {
        var resId = await CmsAssembleControlService.to
            .uploadAttachment(docId!, site, File(element));
        if (resId != null && resId.id != null) {
          if (forGrid) {
            webviewController?.evaluateJavascript(
                source:
                    "layout.app.appForm.uploadedAttachmentDatagrid(\"$site\", \"${resId.id}\", \"$param\")");
          } else {
            webviewController?.evaluateJavascript(
                source:
                    "layout.app.appForm.uploadedAttachment(\"$site\", \"${resId.id}\")");
          }
          OLogger.d('上传附件成功 ${resId.id} ');
        } else {
          errorNumber++;
        }
      }
    }
    if (errorNumber > 0) {
      Loading.showError(
          'process_attachment_upload_error'.trArgs(['$errorNumber']));
    } else {
      Loading.dismiss();
    }
  }

  ///
  /// 替换附件
  ///
  void _replaceAttachment(Map<String, dynamic>? data, {bool forGrid = false}) async {
    if (data != null && docId != null) {
      String site = data["site"] ?? "";
      String attachmentId = data["attachmentId"] ?? "";
      String param = data["param"] ?? "";
      OLogger.d('替换附件 site $site , attachmentId $attachmentId , param $param');
      O2Utils.pickerFileOrImage((paths) {
        _replaceAttachmentBegin(paths, attachmentId, site, param, forGrid);
      });
    }
  }

  Future<void> _replaceAttachmentBegin(List<String?> paths, String attachmentId, String site, String param, bool forGrid) async {
    if (paths.isEmpty) {
      return;
    }
    String path = paths[0] ?? '';
    if (path.isEmpty) {
      return;
    }
    Loading.show();
    OLogger.d('选择了文件：$path');
    var resId = await ProcessSurfaceService.to
        .replaceAttachment(docId!, attachmentId, File(path));
    if (resId != null && resId.id != null) {
      if (forGrid) {
        webviewController?.evaluateJavascript(
            source:
                "layout.app.appForm.replacedAttachmentDatagrid(\"$site\", \"${resId.id}\", \"$param\")");
      } else {
        webviewController?.evaluateJavascript(
            source:
                "layout.app.appForm.replacedAttachment(\"$site\", \"${resId.id}\")");
      }
      OLogger.d('替换附件成功 ${resId.id} ');
      Loading.dismiss();
    }
  }

  ///
  /// 如果有callback函数 就执行
  ///
  void _executeCallbackJs(String? callback, dynamic result) {
    if (callback != null && callback.isNotEmpty) {
      if (result != null) {
        webviewController?.evaluateJavascript(source: '$callback($result)');
      } else {
        webviewController?.evaluateJavascript(source: '$callback()');
      }
    }
  }

  /// 复制当前链接
  void copyLink() async {
    final url = await webviewController?.getUrl();
    if (url != null) {
      Clipboard.setData(ClipboardData(text: url.toString()));
      Loading.toast('im_chat_success_copy'.tr);
    }
  }
}
